
using Common.UGUI.Base;
using Common.UGUI.View;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Common.UGUI {

    public enum LoadUIErrorCode{

        UnKnown = 0,

        BufferError,

        PrefabPathNotRightError,

        UGUIViewTypeNotRightError,
    }

    /// <summary>
    /// UGUIManager可以获取的是Canvas级别和Panel级别的View，那些在每个Panel上具体的部件并不从UGUIManager获取，由对应Panel自己管理
    /// </summary>
	public class UGUIManager //: Manager<UGUIManager> 
    {

        #region 域

        public const string UIRootBundlePath = "UI/";

//#if UNITY_EDITOR
//        private Dictionary<string, UGUIView> _name2UGUIViewDict = new Dictionary<string, UGUIView>(64);
//        private Dictionary<string, UGUICanvas> _name2UGUICanvasDict = new Dictionary<string, UGUICanvas>(16);
//        private Dictionary<string, UGUIPanel>  _name2UGUIPanelDict = new Dictionary<string, UGUIPanel>(64);
//        private Dictionary<string, UGUIImage>  _name2UGUIImageDict = new Dictionary<string, UGUIImage>(64);
//        private Dictionary<string, UGUIButton>  _name2UGUIButtonDict = new Dictionary<string, UGUIButton>(64);
//        private Dictionary<string, UGUIText> _name2UGUITextDict = new Dictionary<string, UGUIText>();
//        private Dictionary<string, UGUIScroller> _name2UGUIScrollerDict = new Dictionary<string, UGUIScroller>(64);
//#else
//        private Dictionary<string, UGUIView> _name2UGUIViewDict = null;
//        private Dictionary<string, UGUICanvas> _name2UGUICanvasDict = null;
//        private Dictionary<string, UGUIPanel> _name2UGUIPanelDict = null;
//        private Dictionary<string, UGUIImage> _name2UGUIImageDict = null;
//        private Dictionary<string, UGUIText> _name2UGUITextDict = null;
//        private Dictionary<string, UGUIButton> _name2UGUIButtonDict = null;
//        private Dictionary<string, UGUIScroller> _name2UGUIScrollerDict = null;
//#endif

        private Dictionary<string, GameObject> _uguiName2Prefab = new Dictionary<string, GameObject>(128);

        private Dictionary<Type, Dictionary<string, UGUIView>> _type2ViewDict = null;

        #endregion

        #region 覆盖Manager虚函数

        //protected override void OnInit() {

        //    _type2ViewDict = new Dictionary<Type, Dictionary<string, UGUIView>>();

        //    _type2ViewDict.Add(typeof(UGUIView), new Dictionary<string, UGUIView>(64));
        //    _type2ViewDict.Add(typeof(UGUICanvas), new Dictionary<string, UGUIView>(64));
        //    _type2ViewDict.Add(typeof(UGUIPanel), new Dictionary<string, UGUIView>(64));
        //    _type2ViewDict.Add(typeof(UGUIImage), new Dictionary<string, UGUIView>(64));
        //    _type2ViewDict.Add(typeof(UGUIButton), new Dictionary<string, UGUIView>(64));
        //    _type2ViewDict.Add(typeof(UGUIScroller), new Dictionary<string, UGUIView>(64));
        //    _type2ViewDict.Add(typeof(UGUIText), new Dictionary<string, UGUIView>(64));
        //}

        //protected override void OnUpdate() { }

        //protected override void OnClear() { }

        //protected override void OnRelease() {

        //    foreach(var pkv in _type2ViewDict) {

        //        Dictionary<string, UGUIView> childDict = pkv.Value;

        //        foreach (var ckv in childDict) {

        //            ckv.Value.Destroy(false);
        //        }

        //        childDict.Clear();
        //    }

        //    _type2ViewDict.Clear();

        //    _type2ViewDict = null;
        //}

        #endregion

        #region 基本方法

        private void RegisterUGUIView(Type type, UGUIView uguiView) {

            //if (HasInited) 
            if(1==0)
            {

                Dictionary<string, UGUIView> dict = _type2ViewDict[type];

                if (Application.isPlaying) {

                    if (!dict.ContainsKey(uguiView.Name)) {

                        dict.Add(uguiView.Name, uguiView);

                    } else {

                        Debug.LogError("UGUIManager RegisterUGUIView with type: " + type.Name + " by UI name \"" + uguiView.Name + "\" has already been registered.");
                    }
                }
            }
        }

        private void RemoveUGUIView(Type type, UGUIView uguiView) {

            // if (HasInited) 
            if (1 == 0)
            {

                Dictionary<string, UGUIView> dict = _type2ViewDict[type];

                if (Application.isPlaying) {

                    if (dict.ContainsKey(uguiView.Name)) {

                        dict.Remove(uguiView.Name);
                    } else {

                        Debug.LogError("UGUIManager RemoveUGUIView with type: " + type.Name + " by UI name \"" + uguiView.Name + "\" has already been removed.");
                    }
                }
            }
        }

        private bool IfHasUGUIView(Type type, string uiName) {

            return !IfNoUGUIView(type, uiName);
        }

        private bool IfNoUGUIView(Type type, string uiName) {

            //if (HasInited) 
            if (1 == 0)
            {

                Dictionary<string, UGUIView> dict = _type2ViewDict[type];

                if (uiName != null) {

                    return !dict.ContainsKey(uiName);
                } else {

                    return true;
                }
            } else {

                return true;
            }
        }

        private UGUIView FetchUGUIView(Type type, string uiName, bool ifLogMessage = true) {

            //if (HasInited)
            if (1 == 0)
            {

                Dictionary<string, UGUIView> dict = _type2ViewDict[type];

                if (dict.ContainsKey(uiName)) {

                    UGUIView targetUI = dict[uiName];

                    if (targetUI == null && ifLogMessage) {

                        Debug.LogError("UGUIManager FetchUGUIView with type: " + type.Name + " by UI name \"" + uiName + "\" be fetched by UGUIManager succeeded but result is null.");
                    }

                    return targetUI;
                } else {

                    if (ifLogMessage) {
                        Debug.Log("<color=#ff0000>UGUIManager FetchUGUIView with type: " + type.Name + " by UI name \"" + uiName + "\" can't be fetched by UGUIManager.</color>");
                    }

                    return null;
                }
            } else {

                if (Application.isPlaying) {

                    //Debug.LogError("UGUIManager FetchUGUIView with type: " + type.Name + " by UI name \"" + uiName + "\" be fetched by UGUIManager failed, UGUIManager hasn't been Inited yet.");
                }

                return null;
            }
        }

        #endregion

        #region 派生接口

        #region UGUI注册

        #region UGUIView

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUIView
        /// </summary>
        public void RegisterUGUIView(UGUIView uguiView, Type type = null) {

            type = type == null || type == typeof(UGUIRoot) ? typeof(UGUIView) : type;

            RegisterUGUIView(type, uguiView);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUIView
        /// </summary>
        public void RemoveUGUIView(UGUIView uguiView, Type type = null) {

            type = type == null || type == typeof(UGUIRoot) ? typeof(UGUIView) : type;

            RemoveUGUIView(type, uguiView);
        }

        #endregion

        #region UGUICanvas

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUICanvas
        /// </summary>
        public void RegisterUGUICanvas(UGUICanvas uguiCanvas) {

            RegisterUGUIView(typeof(UGUICanvas), uguiCanvas);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUICanvas
        /// </summary>
        public void RemoveUGUICanvas(UGUICanvas uguiCanvas) {

            RemoveUGUIView(typeof(UGUICanvas), uguiCanvas);
        }

        #endregion

        #region UGUIPanel

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUIPanel
        /// </summary>
        public void RegisterUGUIPanel(UGUIPanel uguiPanel) {

            RegisterUGUIView(typeof(UGUIPanel), uguiPanel);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUIPanel
        /// </summary>
        public void RemoveUGUIPanel(UGUIPanel uguiPanel) {

            RemoveUGUIView(typeof(UGUIPanel), uguiPanel);
        }

        #endregion

        #region UGUIImage

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUIImage
        /// </summary>
        public void RegisterUGUIImage(UGUIImage uguiImage) {

            RegisterUGUIView(typeof(UGUIImage), uguiImage);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUIImage
        /// </summary>
        public void RemoveUGUIImage(UGUIImage uguiImage) {

            RemoveUGUIView(typeof(UGUIImage), uguiImage);
        }

        #endregion

        #region UGUIButton

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUIButton
        /// </summary>
        public void RegisterUGUIButton(UGUIButton uguiButton) {

           // RegisterUGUIView(typeof(UGUIButton), uguiButton);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUIButton
        /// </summary>
        public void RemoveUGUIButton(UGUIButton uguiButton) {

            //RemoveUGUIView(typeof(UGUIButton), uguiButton);
        }

        #endregion

        #region UGUIText

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUIText
        /// </summary>
        public void RegisterUGUIText(UGUIText uguiText) {

            RegisterUGUIView(typeof(UGUIText), uguiText);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUIText
        /// </summary>
        public void RemoveUGUIText(UGUIText uguiText) {

            RemoveUGUIView(typeof(UGUIText), uguiText);
        }

        #endregion

        #region UGUIScroller

        /// <summary>
        /// 框架接口，业务流程中不要调用，在Manager中注册一个UGUIScroller
        /// </summary>
        public void RegisterUGUIScroller(UGUIScroller uguiScroller) {

            RegisterUGUIView(typeof(UGUIScroller), uguiScroller);
        }

        /// <summary>
        /// 框架接口，业务流程中不要主动调用，移除Mananger中注册的一个UGUIScroller
        /// </summary>
        public void RemoveUGUIScroller(UGUIScroller uguiScroller) {

            RemoveUGUIView(typeof(UGUIScroller), uguiScroller);
        }

        #endregion

        #endregion

        #region UGUI查询

        #region UGUIView

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUIView
        /// </summary>
        public bool IfHasUGUIView(string uiName, Type type = null) {

            type = type == null || type == typeof(UGUIRoot) ? typeof(UGUIView) : type;

            return IfHasUGUIView(type, uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUIView
        /// </summary>
        public bool IfNoUGUIView(string uiName, Type type = null) {

            type = type == null || type == typeof(UGUIRoot) ? typeof(UGUIView) : type;

            return IfNoUGUIView(type, uiName);
        }

        #endregion

        #region UGUICanvas

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUICanvas
        /// </summary>
        public bool IfHasUGUICanvas(string uiName) {

            return IfHasUGUIView(typeof(UGUICanvas), uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUICanvas
        /// </summary>
        public bool IfNoUGUICanvas(string uiName) {

            return IfNoUGUIView(typeof(UGUICanvas), uiName);
        }

        #endregion

        #region UGUIPanel

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUIPanel
        /// </summary>
        /// <returns>true有,false无</returns>
        public bool IfHasUGUIPanel(string uiName) {

            return IfHasUGUIView(typeof(UGUIPanel), uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUIPanel
        /// </summary>
        public bool IfNoUGUIPanel(string uiName) {

            return IfNoUGUIView(typeof(UGUIPanel), uiName);
        }

        #endregion

        #region UGUIImage

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUIImage
        /// </summary>
        /// <returns>true有,false无</returns>
        public bool IfHasUGUIImage(string uiName) {

            return IfHasUGUIView(typeof(UGUIImage), uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUIImage
        /// </summary>
        public bool IfNoUGUIImage(string uiName) {

            return IfNoUGUIView(typeof(UGUIImage), uiName);
        }

        #endregion

        #region UGUIButton

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUIButton
        /// </summary>
        /// <returns>true有,false无</returns>
        public bool IfHasUGUIButton(string uiName) {

            return IfHasUGUIView(typeof(UGUIButton), uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUIButton
        /// </summary>
        public bool IfNoUGUIButton(string uiName) {

            return IfNoUGUIView(typeof(UGUIButton), uiName);
        }

        #endregion

        #region UGUIText

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUIText
        /// </summary>
        /// <returns>true有,false无</returns>
        public bool IfHasUGUIText(string uiName) {

            return IfHasUGUIView(typeof(UGUIText), uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUIText
        /// </summary>
        public bool IfNoUGUIText(string uiName) {

            return IfNoUGUIView(typeof(UGUIText), uiName);
        }

        #endregion

        #region UGUIScroller

        /// <summary>
        /// 是否UGUIManager已经注册了某个UGUIScroller
        /// </summary>
        public bool IfHasUGUIScroller(string uiName) {

            return IfHasUGUIView(typeof(UGUIScroller), uiName);
        }

        /// <summary>
        /// 是否UGUIManager任未注册某个UGUIScroller
        /// </summary>
        public bool IfNoUGUIScroller(string uiName) {

            return IfNoUGUIView(typeof(UGUIScroller), uiName);
        }

        #endregion

        #endregion

        #region UGUI获取

        public UGUIView FetchUGUIView(string uiName, Type type, bool ifLogMessage = true) {

            type = type == null || type == typeof(UGUIRoot) ? typeof(UGUIView) : type;

            return FetchUGUIView(type, uiName, ifLogMessage);
        }

        public UGUICanvas FetchUGUICanvas(string uiName, bool ifLogMessage = true) {

            return FetchUGUIView(typeof(UGUICanvas), uiName, ifLogMessage) as UGUICanvas;
        }

        public UGUIPanel FetchUGUIPanel(string uiName, bool ifLogMessage = true) {

            return FetchUGUIView(typeof(UGUIPanel), uiName, ifLogMessage) as UGUIPanel;
        }

        public UGUIImage FetchUGUIImage(string uiName, bool ifLogMessage = true) {

            return FetchUGUIView(typeof(UGUIImage), uiName, ifLogMessage) as UGUIImage;
        }
        /// <summary>
        /// Fetch????
        /// </summary>
        /// <param name="uiName"></param>
        /// <param name="ifLogMessage"></param>
        /// <returns></returns>
        public UGUIButton FetchUGUIButton(string uiName, bool ifLogMessage = true) {

            //return FetchUGUIView(typeof(UGUIButton), uiName, ifLogMessage) as UGUIButton;
            return null;
        }

        public UGUIText FetchUGUIText(string uiName, bool ifLogMessage = true) {

            return FetchUGUIView(typeof(UGUIText), uiName, ifLogMessage) as UGUIText;
        }

        public UGUIScroller FetchUGUIScroller(string uiName, bool ifLogMessage = true) {

            return FetchUGUIView(typeof(UGUIScroller), uiName, ifLogMessage) as UGUIScroller;
        }

        #endregion

        #endregion

        #region 资源加载

        /// <summary>
        /// 加载一个UGUI的实例对象, 注意OnSuccess里面返回的对象一定不为空
        /// </summary>
        /// <param name="bundleName">bundle路径名</param>
        /// <param name="uiName">bundle内的prefab名</param>
        /// <param name="parent">父对象</param>
        /// <param name="onSuccess">加载成功回调</param>
        /// <param name="onFailed">加载失败回调</param>
        public void NewGameObjectByName<T>(string bundleName, string uiName, UGUIView parent, Action<T> onSuccess, Action<LoadUIErrorCode> onFailed) where T : UGUIView {

            string indexName = UIRootBundlePath + bundleName + uiName;

            if (_uguiName2Prefab.ContainsKey(indexName)) {

                if (_uguiName2Prefab[indexName] != null) {

                    if (onSuccess != null) {

                        //onSuccess(GameObject.Instantiate(_uguiName2Prefab[indexName]));
                        string bundlePath = UIRootBundlePath + bundleName;
                        // Logger.Log("**** UGUIManager LoadPrefabByName bundlePath is <color=#0000ff>" + bundlePath + "</color>");

                        // GameObject newUGUIGO = AssetBundleManager.Instance.LoadBaseAsset<GameObject>(bundlePath, uiName + ".prefab", null);
                        GameObject newUGUIGO = null;
                        if (newUGUIGO != null) {

                            T uguiView = newUGUIGO.GetComponent<T>();

                            if (uguiView != null) {

                                uguiView.SetParent(parent);

                                onSuccess(uguiView);
                            } else {

                                GameObject.Destroy(newUGUIGO);

                                Debug.LogError("UGUIManager NewGameObjectByName error: loaded prefab must have uguiView component with type: " + typeof(T).Name + " at top level.");

                                if (onFailed != null) {

                                    onFailed(LoadUIErrorCode.UGUIViewTypeNotRightError);
                                }
                            }
                        } else {

                            if (onFailed != null) {

                                onFailed(LoadUIErrorCode.PrefabPathNotRightError);
                            }
                        }
                    }
                } else {

                    Debug.LogError("UGUIManager NewGameObjectByName error, prefab dict has key: " + indexName + " but value is null.");

                    if (onFailed != null) {

                        onFailed(LoadUIErrorCode.BufferError);
                    }
                }
            } else {

                LoadPrefabByName<T>(bundleName, uiName, parent, onSuccess, onFailed);
            }
        }

        // TODO: 现在能提供的加载接口不需要去缓存Asset，以后应该要
        private void LoadPrefabByName<T>(string bundleName, string uiName, UGUIView parent, Action<T> onSuccess, Action<LoadUIErrorCode> onFailed) where T : UGUIView {

            if (onSuccess != null) {
                
                string bundlePath = UIRootBundlePath + bundleName;

                //GameObject newUGUIGO = AssetBundleManager.Instance.LoadBaseAsset<GameObject>(bundlePath, uiName + ".prefab", null);
                GameObject newUGUIGO = null;
                if (newUGUIGO != null) {

                    T uguiView = newUGUIGO.GetComponent<T>();

                    if (uguiView != null) {

                        uguiView.SetParent(parent);

                        onSuccess(uguiView);
                    } else {

                        GameObject.Destroy(newUGUIGO);

                        Debug.LogError("UGUIManager NewGameObjectByName error: loaded prefab must have uguiView component with type: " + typeof(T).Name + " at top level.");

                        if (onFailed != null) {

                            onFailed(LoadUIErrorCode.UGUIViewTypeNotRightError);
                        }
                    }
                } else {

                    if (onFailed != null) {

                        onFailed(LoadUIErrorCode.PrefabPathNotRightError);
                    }
                }
            }
        }

        #endregion
    }
}
